package com.example.sourcecodelearning.concurrent;

import lombok.SneakyThrows;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 两个线程交替输出奇偶数
 */
public class ConcurrentPrintNumber {

    public static void main(String[] args) {
        test1();
        //test2();
    }

    private static int a = 1;

    /**
     * 自己写的版本，通过wait和notify实现同步机制
     */
    @SneakyThrows
    private static void test1() {
        System.out.println("开始");

        final Object lock = new Object();

        Thread thread1 = new Thread(() -> {
            while (a <= 100) {
                synchronized (lock) {
                    if (a % 2 == 1) {
                        System.out.println("t1:" + a++);
                        lock.notify();
                    } else {
                        // 不能直接阻塞，否则最后一次无法被唤醒
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            while (a <= 100) {
                synchronized (lock) {
                    if (a % 2 == 0) {
                        System.out.println("t2:" + a++);
                        lock.notify();
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("结束");
    }

    /**
     * ChatGPT 优化后的版本，使用 ReentrantLock 和 Condition 实现同步
     */
    @SneakyThrows
    private static void test2() {
        System.out.println("开始");

        AtomicInteger a = new AtomicInteger(0);
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();

        Thread thread1 = new Thread(() -> {
            while (a.get() <= 100) {
                lock.lock();
                if (a.get() % 2 == 0) {
                    System.out.println("t1:" + a.getAndIncrement());
                    condition.signal();
                } else {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                lock.unlock();
            }
        });

        Thread thread2 = new Thread(() -> {
            while (a.get() <= 100) {
                lock.lock();
                if (a.get() % 2 == 1) {
                    System.out.println("t2:" + a.getAndIncrement());
                    condition.signal();
                } else {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                lock.unlock();
            }
        });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("结束");
    }

}
